﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Client
{

    /// <summary>
    /// 微软自带的SocketClient
    /// </summary>
    public class SocketClientHelper
    {
        public int ID { get; set; }
        /// <summary>
        /// 服务器端IP
        /// </summary>
        public string _ServerIP;
        /// <summary>
        /// 服务器端端口
        /// </summary>
        public int _ServerPort;
        /// <summary>
        /// 服务器端IP
        /// </summary>
        public string _BindIP;
        /// <summary>
        /// 绑定本地端口
        /// </summary>
        public int _BindPort;
        /// <summary>
        /// 客户端Socket对象
        /// </summary>
        private Socket _Client;
        /// <summary>
        /// 接收线程
        /// </summary>
        public Thread _ThreadRecive;

        string _SocketName = "";
        /// <summary>
        /// 接收信息事件
        /// </summary>
        public event Action<string> ReciveEvent;

        public CancellationTokenSource ReciveState;
        public SocketClientHelper(string TargetIp, int TargetPort, string SocketName, string BindIP = null, int BindPort = 0)
        {
            _ServerIP = TargetIp;
            _ServerPort = TargetPort;
            _BindIP = BindIP;
            _BindPort = BindPort;
            _SocketName = SocketName;
        }

        /// <summary>
        /// 是否连接(不能搞频率调用)
        /// </summary>
        /// <returns></returns>
        public bool IsConnected()
        {
            if (_Client == null)
            {
                return false;
            }
            bool blockingState = _Client.Blocking;
            try
            {
                try
                {
                    byte[] tmp = new byte[1];
                    if (_Client != null)
                    {
                        _Client.Blocking = false;
                        _Client.Send(tmp, 0, 0);
                    }
                    else
                    {
                        return false;
                    }

                    return true;
                }
                catch (SocketException e)
                {
                    // 产生 10035 == WSAEWOULDBLOCK 错误，说明被阻止了，但是还是连接的
                    if (e.NativeErrorCode.Equals(10035))
                        return true;
                    else
                        return false;
                }
                finally
                {
                    _Client.Blocking = blockingState;    // 恢复状态
                }
            }
            catch (SocketException e)
            {
                // 产生 10035 == WSAEWOULDBLOCK 错误，说明被阻止了，但是还是连接的
                if (e.NativeErrorCode.Equals(10035))
                    return true;
                else
                    return false;
            }
        }

        /// <summary>
        /// 服务开启
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            try
            {
                if (State == 0)
                {
                    State = 1;
                    IPAddress ip = IPAddress.Parse(_ServerIP);
                    //创建端口号对象  
                    IPEndPoint point = new IPEndPoint(ip, _ServerPort);
                    IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
                    IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
                    if (ipEndPoints.Contains(point))
                    {
                        if (_Client != null)
                        {
                            _Client.Close();
                            _Client.Dispose();
                        }

                    }
                    //创建客户端Socket对象
                    _Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    //_Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                    _Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);


                    if (_BindIP != null && _BindPort != 0)
                    {
                        IPAddress BindIpLogin = IPAddress.Parse(_BindIP);//绑定本地IP
                        IPEndPoint BindPoint = new IPEndPoint(BindIpLogin, _BindPort);//绑定本地端口
                        _Client.Bind(BindPoint);
                    }

                    if (_ThreadRecive == null || !_ThreadRecive.IsAlive)
                    {
                        _ThreadRecive = new Thread(Recive);
                        //获取远程连接的服务器的IP地址和端口号
                        _Client.Connect(point);
                        if (!string.IsNullOrEmpty(_SocketName))
                        {
                            SendServer("SocketName," + _SocketName);
                        }

                        //开启新线程不停的接收服务端发来的信息              
                        _ThreadRecive.IsBackground = true;
                        ReciveState = new CancellationTokenSource();
                        _ThreadRecive.Start();
                    }
                    return true;
                }
                else
                {

                    return false;

                }

            }
            catch (Exception ex)
            {

                return false;
            }
        }
        int State = 0;
        /// <summary>
        /// 关闭服务
        /// </summary>
        /// <returns></returns>
        public bool Close()
        {
            try
            {
                State = 0;
                if (_Client != null)
                {
                    if (ReciveState != null)
                    {

                        ReciveState.Cancel();//接收线程终止
                        //_ThreadRecive.Abort();
                        //Thread.Sleep(30);
                    }

                    //_ThreadRecive.Abort();//接收线程终止
                    _Client.Close();

                    _Client.Dispose();
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }

        /// <summary>
        ///创建线程方法不停接收服务端发的信息
        /// </summary>
        void Recive()
        {
            bool Break = false;
            int count = 0;
            while (!ReciveState.IsCancellationRequested)
            {
                try
                {
                    if (IsConnected())
                    {
                        byte[] buffer = new byte[1024 * 1024 * 3];
                        int r = _Client.Receive(buffer);//阻塞代码

                        if (r == 0)//断线
                        {
                            Break = true;
                        }
                        Task.Run(() =>
                        {

                            string Str = Encoding.Default.GetString(buffer, 0, r);//从1开始读取
                            ReciveEvent?.Invoke(Str);//返回委托方法

                        });
                        if (Break)
                        {
                            break;
                        }
                    }
                    else
                    {
                        return;
                    }
                }
                catch (SocketException e)
                {
                    // 产生 10035 == WSAEWOULDBLOCK 错误，说明被阻止了，但是还是连接的
                    if (e.NativeErrorCode.Equals(10035))
                    {
                        _Client.Blocking = true;
                        continue;
                    }
                    else
                        return;
                }
            }

        }
        /// <summary>
        /// 给服务端发送信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public bool SendServer(string str)
        {
            try
            {
                //byte[] buffer = Encoding.GetEncoding("gb18030").GetBytes(str);
                byte[] buffer = Encoding.Default.GetBytes(str);
                int a = _Client.Send(buffer);
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }
    }
}
